package com.kedll.library.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;

import com.kedll.library.R;
import com.kedll.library.util.StringUtil;

import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 具有数字滚动效果的TextView
 * TODO: document your custom view class.
 */
public class NumberRunTextView extends android.support.v7.widget.AppCompatTextView {

    private final static int MONEY_TYPE = 0;
    private final static int NUM_TYPE = 1;

    private String preStr;//记录上一次的内容
    private int frameNum;//帧数
    private boolean useCommaFormat;//是否使用每三个数字一个逗号
    private boolean runWhenChange;//是否每次发生改变是执行动画
    private int textType;//数字类型
    private double finalMoneyNum;//最终的金额数字
    private int finalNum;//最终的整数数字
    private double nowMoneyNum = 0;
    private int nowNum = 0;
    private Executor threadPool = Executors.newFixedThreadPool(1);
    private MyHandler handler;

    private DecimalFormat formatter = new DecimalFormat("0.00");

    public NumberRunTextView(Context context) {
        super(context);
        init(null, 0);
    }

    public NumberRunTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public NumberRunTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {
        // Load attributes
        final TypedArray a = getContext().obtainStyledAttributes(
                attrs, R.styleable.NumberRunTextView, defStyle, 0);

        useCommaFormat = a.getBoolean(R.styleable.NumberRunTextView_useCommaFormat, true);
        runWhenChange = a.getBoolean(R.styleable.NumberRunTextView_runWhenChange, true);
        textType = a.getInt(R.styleable.NumberRunTextView_textType, MONEY_TYPE);
        frameNum = a.getInt(R.styleable.NumberRunTextView_frameNum, 30);

        a.recycle();

        handler = new MyHandler(this);

        // Update TextPaint and text measurements from attributes
    }

    public void setContent(String str) {
        if (TextUtils.isEmpty(str)) {
            return;
        }

        if ("--".equals(str)) {
            preStr = str;
            setText(str);
            return;
        }

        //如果当内容改变时，才执行滚动动画
        if (runWhenChange) {
            if (TextUtils.isEmpty(preStr)) {
                //如果上一次的str为空
                preStr = str;
                useAnimByType(str);
                return;
            }

            //如果上一次的不为空，则判断两次的内容是否一致
            if (preStr.equals(str)) {
                //如果两次的内容一致，则不做处理
                return;
            }
            preStr = str;
        }

        useAnimByType(str);
    }

    private void useAnimByType(String str) {
        if (textType == MONEY_TYPE) {
            playMoneyAnim(str);
        } else {
            playNumAnim(str);
        }
    }

    /**
     * 播放整数数字动画的方法
     *
     * @param str
     */
    private void playNumAnim(String str) {
        //如果传入的数字已经使用逗号格式化的，或者含有负号，去除逗号和负号
        String num = str.replace(",", "").replace("-", "");
        try {
            finalNum = Integer.parseInt(num);
            if (finalNum < frameNum) {
                this.setText(str);
                return;
            }

            nowNum = 0;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    Message msg = handler.obtainMessage();
                    int temp = finalNum / frameNum;
                    msg.what = NUM_TYPE;
                    msg.obj = temp;
                    handler.sendMessage(msg);
                }
            });

        } catch (NumberFormatException e) {
            e.printStackTrace();
            this.setText(str);
        }
    }

    /**
     * 播放金额数字动画的方法
     *
     * @param str
     */
    private void playMoneyAnim(String str) {
        //如果传入的数字已经使用逗号格式化的，或者含有负号，去除逗号和负号
        String money = str.replace(",", "").replace("-", "");
        try {
            finalMoneyNum = Double.parseDouble(money);
            if (finalMoneyNum == 0) {
                //如果传入的为0， 则直接使用setText
                this.setText(str);
                return;
            }
            nowMoneyNum = 0;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    Message msg = handler.obtainMessage();
                    //金额数字除以帧数，得到每帧跳跃的数字
                    double size = finalMoneyNum / frameNum;
                    msg.what = MONEY_TYPE;
                    //如果每帧的间隔小于0.01，则设置为0.01
                    msg.obj = size < 0.01 ? 0.01 : size;
                    handler.sendMessage(msg);
                }
            });

        } catch (NumberFormatException e) {
            e.printStackTrace();
            //如果转换double失败，则直接使用setText
            this.setText(str);
        }
    }

    /**
     * 给金额数字的每三个数添加一个逗号
     *
     * @param str
     *
     * @return
     */
    private String addComma(String str) {
        if (TextUtils.isEmpty(str)) {
            return null;
        }

        //获取整数部分
        String integerPart;
        //小数部分
        String decimalPart;
        String[] parts = str.split("\\.");
        integerPart = parts[0];
        decimalPart = parts[1];

        //如果整数部分的长度小于等于3，则直接返回
        int integerPartLength = StringUtil.strLength(integerPart);
        if (integerPartLength <= 3) {
            return str;
        }
        //计算总的逗号数
        int commaCount = integerPartLength / 3;
        if (integerPartLength % 3 == 0) {
            commaCount -= 1;
        }
        char[] integerChars = integerPart.toCharArray();
        //新建一个字符数组，长度是整数部分的长度+逗号数
        char[] newStrs = new char[integerPartLength + commaCount];
        int charPoint = 0;//记录当前已经复制的字符数
        for (int i = newStrs.length - 1; i >= 0; i--) {
            newStrs[i] = integerChars[i - commaCount];
            charPoint++;
            //已经复制了3个，清零重新计数，已添加逗号数减一
            if (charPoint == 3) {
                charPoint = 0;
                commaCount--;
                i--;
                if (i > 0) {
                    newStrs[i] = ',';//每三个数字，插入一个逗号
                }
            }
        }
        StringBuilder builder = new StringBuilder();
        builder.append(newStrs).append(".").append(decimalPart);
        return builder.toString();
    }

    private static class MyHandler extends Handler {
        private WeakReference<NumberRunTextView> ref;

        public MyHandler(NumberRunTextView view) {
            ref = new WeakReference<>(view);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            NumberRunTextView runTextView = ref.get();
            if (runTextView == null) {
                return;
            }

            switch (msg.what) {
                case MONEY_TYPE://金钱数字的滚动
                    String str = runTextView.formatter.format(runTextView.nowMoneyNum);
                    if (runTextView.useCommaFormat) {//使用每三个数字一个逗号的格式
                        String formatStr = runTextView.addComma(str);
                        runTextView.setText(formatStr);
                    } else {
                        runTextView.setText(str);
                    }

                    /* 记录当前递增后的金额数字 */
                    runTextView.nowMoneyNum += (double) msg.obj;

                    if (runTextView.nowMoneyNum < runTextView.finalMoneyNum) {
                        //如果当前记录的金额数字小于目标金额数字，继续递增
                        Message msg2 = runTextView.handler.obtainMessage();
                        msg2.what = MONEY_TYPE;
                        msg2.obj = msg.obj;
                        runTextView.handler.sendMessage(msg2);
                    } else {
                        if (runTextView.useCommaFormat) {//使用每三个数字一个逗号的格式
                            String formatStr = runTextView.addComma(runTextView.formatter.format(runTextView.finalMoneyNum));
                            runTextView.setText(formatStr);
                        } else {
                            //已经到达，显示最终金额数字
                            runTextView.setText(runTextView.formatter.format(runTextView.finalMoneyNum));
                        }

                    }

                    break;
                case NUM_TYPE://普通数字滚动
                    runTextView.setText(String.valueOf(runTextView.nowNum));
                    runTextView.nowNum += (Integer) msg.obj;//记录每帧递增后的数字
                    if (runTextView.nowNum < runTextView.finalNum) {
                        //如果当前记录的数字小于目标数字，继续递增
                        Message msg2 = runTextView.handler.obtainMessage();
                        msg2.what = NUM_TYPE;
                        msg2.obj = msg.obj;
                        runTextView.handler.sendMessage(msg2);
                    } else {
                        //已经到达，显示最终数字
                        runTextView.setText(String.valueOf(runTextView.finalNum));
                    }

                    break;
            }
        }
    }

}
